<template>
  <div class="editor-container">
    <div ref="editorRef" class="editor"></div>
  </div>
</template>

<script setup lang="ts">
import eventBus from '@/utils/event-bus'
import * as monaco from 'monaco-editor'
/*import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'*/
import { language as sqlLanguage } from 'monaco-editor/esm/vs/basic-languages/sql/sql.js'

defineOptions({
  name: 'EditorComponent',
})
type Props = {
  mode: string,
  readonly: boolean,
}
const editorRef = ref(null)
let editor = null
const value = defineModel<string>()
const props = defineProps<Props>()
/* self.MonacoEnvironment = {
  getWorker(_, label) {
    console.log('getWorker', label)
    if (label === 'json') {
      return new jsonWorker()
    }
    if (label === 'css' || label === 'scss' || label === 'less') {
      return new cssWorker()
    }
    if (label === 'html' || label === 'handlebars' || label === 'razor') {
      return new htmlWorker()
    }
    if (label === 'typescript' || label === 'javascript') {
      return new tsWorker()
    }
    // 默认返回 editor worker
    return new editorWorker()
  },
} */
onMounted(() => {
  nextTick(() => {
    if (props.mode === 'sql') {
      registerSQLLanguage()
    }
    editor = monaco.editor.create(editorRef.value, {
      value: value.value,
      language: props.mode,
      fontSize: 14,
      readOnly: props.readonly,
      theme: 'vs-light',
      minimap: {
        enabled: true,
      },
      automaticLayout: true,
      tabSize: 2,
      fontFamily: 'Consolas,Monaco,monospace',
      fontLigatures: true,
      scrollBeyondLastLine: false,
      wordWrap: 'on',
      wrappingIndent: 'indent',
    })
    editor.onDidChangeModelContent(() => {
      // emit('update:modelValue', editor.getValue())
      console.log(editor.getValue())
      value.value = editor.getValue()
    })
  })
  eventBus.$on('hasSyntaxErrors', hasSyntaxErrors)
})
const hasSyntaxErrors = (callback) => {
  const markers = monaco.editor.getModelMarkers({ resource: editor.getModel().uri })
  const errorMarkers = markers.filter(marker =>
    marker.severity === monaco.MarkerSeverity.Error,
  )
  if (errorMarkers.length > 0) {
    callback(true)
  } else {
    callback(false)
  }
}
const registerSQLLanguage = () => {
  monaco.languages.registerCompletionItemProvider('sql', {
    provideCompletionItems: function() {
      let suggestions = []
      sqlLanguage.keywords.forEach(item => {
        suggestions.push({
          label: item,
          kind: monaco.languages.CompletionItemKind.Keyword,
          insertText: item,
        })
      })
      sqlLanguage.operators.forEach(item => {
        suggestions.push({
          label: item,
          kind: monaco.languages.CompletionItemKind.Operator,
          insertText: item,
        })
      })
      sqlLanguage.builtinFunctions.forEach(item => {
        suggestions.push({
          label: item,
          kind: monaco.languages.CompletionItemKind.Function,
          insertText: item,
        })
      })
      sqlLanguage.builtinVariables.forEach(item => {
        suggestions.push({
          label: item,
          kind: monaco.languages.CompletionItemKind.Variable,
          insertText: item,
        })
      })
      return {
        suggestions: suggestions,
      }
    },
  })
}
onUnmounted(() => {
  editor.dispose()
  eventBus.$off('hasSyntaxErrors', hasSyntaxErrors)
})
/*
export default {
	name: 'CodeEditor',
	props: {
		modelValue: {
			type: String,
			//required: true
		},
		readonly: {
			type: Boolean,
			default: false
		},
		mode: {
			type: String,
			default: 'javascript'
		},
		userWorker: {  //是否开启语法检查，默认开启
			type: Boolean,
			default: true
		},

	},
	watch: {
		modelValue(val) {
			if (val !== this.aceEditor.getValue()) {
				this.aceEditor.setValue(val)
			}
		}
	},
	emits: ['update:modelValue'],
	mounted() {
		//ace.config.set('basePath', 'https://ks3-cn-beijing.ksyun.com/vform2021/ace')
		ace.config.set('basePath', ACE_BASE_PATH)

		this.addAutoCompletion(ace)  //添加自定义代码提示！！

		this.aceEditor = ace.edit(this.$refs.ace, {
			maxLines: 20, // 最大行数，超过会自动出现滚动条
			minLines: 5, // 最小行数，还未到最大行数时，编辑器会自动伸缩大小
			fontSize: 12, // 编辑器内字体大小
			theme: this.themePath, // 默认设置的主题
			mode: this.modePath, // 默认设置的语言模式
			tabSize: 2, // 制表符设置为2个空格大小
			readOnly: this.readonly,
			highlightActiveLine: true,
			value: this.modelValue
		})

		this.aceEditor.setOptions({
			enableBasicAutocompletion: true,
			enableSnippets: true,  // 设置代码片段提示
			enableLiveAutocompletion: true,  // 设置自动提示
		})

		if (this.mode === 'json') {
			this.setJsonMode()
		} else if (this.mode === 'css') {
			this.setCssMode()
		}

		if (!this.userWorker) {
			this.aceEditor.getSession().setUseWorker(false)
		}

		//编辑时同步数据
		this.aceEditor.getSession().on('change', (ev) => {
			this.$emit('update:modelValue', this.aceEditor.getValue())
		})
	},
	data() {
		return {
			aceEditor: null,
			themePath: 'ace/theme/sqlserver', // 不导入 webpack-resolver，该模块路径会报错
			modePath: 'ace/mode/javascript', // 同上
			codeValue: this.modelValue
		}
	},
	methods: {
		addAutoCompletion(ace) {
			let acData = [
				{meta: 'VForm API', caption: 'getWidgetRef', value: 'getWidgetRef()', score: 1},
				{meta: 'VForm API', caption: 'getFormRef', value: 'getFormRef()', score: 1},
				{meta: 'VForm API', caption: 'getParentFormRef', value: 'getParentFormRef()', score: 1},
				//TODO: 待补充！！
			]
			let langTools = ace.require('ace/ext/language_tools')
			langTools.addCompleter({
				getCompletions: function (editor, session, pos, prefix, callback) {
					if (prefix.length === 0) {
						return callback(null, []);
					} else {
						return callback(null, acData);
					}
				}
			})
		},

		setJsonMode() {
			this.aceEditor.getSession().setMode('ace/mode/json')
		},

		setCssMode() {
			this.aceEditor.getSession().setMode('ace/mode/css')
		},

		getEditorAnnotations() {
			return this.aceEditor.getSession().getAnnotations()
		},

		setValue(newValue) {
			this.aceEditor.getSession().setValue(newValue)
		},

	}
}
*/
</script>

<style lang="scss" scoped>
.editor-container {
  width: 100%;
  position: relative;
}

.editor {
  min-height: 60vh;
  width: 100%;
}
</style>
